﻿using System;
using System.Linq;
using NHibernate.Linq;
using nsadv.Statistic.Domain;
using nsadv.Statistic.Repository.NHibernate.Sessions;
using System.Collections.Generic;
using System.Text;

namespace nsadv.Statistic.Repository.NHibernate
{
	public class Statistic : IStatistic
	{
		protected readonly INHibernateSessionController SessionController;

		public Statistic(INHibernateSessionController sessionController)
		{
			SessionController = sessionController;
		}

		private string BuildPeriodFilter(DateTime? from, DateTime? to)
		{
			StringBuilder builder = new StringBuilder();

			if (from.HasValue)
				builder.AppendLine(string.Format("  EventDate >= '{0}' and", from.Value.ToString("s")));

			if (to.HasValue)
			{
				var toVal = to.Value;
				if (toVal.TimeOfDay == TimeSpan.Zero)
					toVal = toVal.Date.AddDays(1).AddSeconds(-1);
				builder.AppendLine(string.Format("  EventDate <= '{0}' and", toVal.ToString("s")));
			}

			return builder.ToString();
		}

		public IEnumerable<BannerPeriodicalRow> BannerPeriodical(Banner banner, Platform platform, Advertiser adv, Place place,
			PeriodicalGroupping groupping, DateTime? from = null, DateTime? to = null)
		{
			string datePart = "";

			switch (groupping)
			{
				case PeriodicalGroupping.Day:
					datePart = "dd";
					break;
				case PeriodicalGroupping.Week:
					datePart = "ww";
					break;
				case PeriodicalGroupping.Month:
					datePart = "mm";
					break;
			}

			string query = String.Format(@"
select 
  DATEDIFF({0}, '1900-01-01', Stats.EventDate) as 'Offset', 
  DATEADD({0}, DATEDIFF({0}, '1900-01-01', Stats.EventDate), '1900-01-01') as 'StartDate',
  (select sum(StatsInner.Count)
   from 
	 Stats StatsInner
		left join Banners b on StatsInner.BannerId = b.Id
			left join Campaigns c on b.CampaignId = c.Id
   where
	 StatsInner.BannerId = Stats.BannerId and
	 DATEDIFF({0}, '1900-01-01', Stats.EventDate) = DATEDIFF({0}, '1900-01-01', StatsInner.EventDate) and
	 EventId = {3}
	{8}
	{9}
	{10})
	as 'ShowCount'
, 
  (select sum(StatsInner.Count)
   from 
	 Stats StatsInner
		left join Banners b on StatsInner.BannerId = b.Id
			left join Campaigns c on b.CampaignId = c.Id
   where
	 StatsInner.BannerId = Stats.BannerId and 
	 DATEDIFF({0}, '1900-01-01', Stats.EventDate) = DATEDIFF({0}, '1900-01-01', StatsInner.EventDate) and
	 EventId = {4}
	{8}
	{9}
	{10})
	as 'ClickCount'
,
  (select count(distinct StatsInner.DeviceId)
   from 
	 Stats StatsInner
		left join Banners b on StatsInner.BannerId = b.Id
			left join Campaigns c on b.CampaignId = c.Id
   where
	 StatsInner.BannerId = Stats.BannerId and 
	 DATEDIFF({0}, '1900-01-01', Stats.EventDate) = DATEDIFF({0}, '1900-01-01', StatsInner.EventDate) and
	 EventId = {4}
	{8}
	{9}
	{10})
	as 'UniqueClickCount'
,
  (select sum(StatsInner.Count)
   from 
	 Stats StatsInner
		left join Banners b on StatsInner.BannerId = b.Id
			left join Campaigns c on b.CampaignId = c.Id
   where
	 StatsInner.BannerId = Stats.BannerId and 
	 DATEDIFF({0}, '1900-01-01', Stats.EventDate) = DATEDIFF({0}, '1900-01-01', StatsInner.EventDate) and
	 EventId = {5}
	{8}
	{9}
	{10})
	as 'ExpandCount'
from 
  Stats
	left join Banners b on Stats.BannerId = b.Id
		left join Campaigns c on b.CampaignId = c.Id
where
{1}
  Stats.BannerId = '{2}'
{6}
{7}
{10}
group by
  Stats.BannerId, DATEDIFF({0}, '1900-01-01', Stats.EventDate)
order by
  DATEDIFF({0}, '1900-01-01', Stats.EventDate)", 
	  datePart, 
	  BuildPeriodFilter(from, to),  
	  banner.Id,
	  (int)EventType.Show,
	  (int)EventType.Click,
	  (int)EventType.ShowFullscreen,
	  platform == null ? "" : string.Format(" AND Stats.PlatformId ='{0}' ", platform.Id),
	  place == null ? "" : string.Format(" AND Stats.PlaceId ='{0}' ", place.Id),
	  platform == null ? "" : string.Format(" AND StatsInner.PlatformId ='{0}' ", platform.Id),
	  place == null ? "" : string.Format(" AND StatsInner.PlaceId ='{0}' ", place.Id),
	  adv == null ? "" : string.Format(" AND c.AdvertiserId ='{0}' ", adv.Id)
	  );

			var rowList =  SessionController.Current.CreateSQLQuery(query).List();

			foreach (object[] row in rowList)
			{
				var result = new BannerPeriodicalRow
								{
									Offset = (int) row[0],
									StartDate = (DateTime) row[1],
									ShowCount = (int) (row[2] ?? 0),
									ClickCount = (int) (row[3] ?? 0),
									UniqueClickCount = (int) (row[4] ?? 0),
									ExpandCount = (int) (row[5] ?? 0)
								};

				yield return result;
			}
		}
	}
}
